package org.ehe.erp.service.purchase.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.ehe.business.bom.domain.BomMaster;
import org.ehe.business.bom.service.BomMasterService;
import org.ehe.business.monitor.MonitorMethod;
import org.ehe.business.overdue.config.OverdueStatus;
import org.ehe.business.overdue.extract.PurcharOrderDataExtractor;
import org.ehe.business.project.domain.ProjectSolution;
import org.ehe.business.supplier.domain.SupplierInfo;
import org.ehe.business.supplier.service.SupplierInfoService;
import org.ehe.business.timeout.contants.BizTypeConstant;
import org.ehe.business.timeout.domain.SsePushMessage;
import org.ehe.business.timeout.domain.TimeoutInstance;
import org.ehe.business.timeout.domain.vo.TimeoutInstanceVo;
import org.ehe.business.timeout.event.BusinessEvent;
import org.ehe.business.timeout.event.RemindEvent;
import org.ehe.business.timeout.mapper.SsePushMessageMapper;
import org.ehe.business.timeout.mapper.TimeoutConfigMapper;
import org.ehe.business.timeout.mapper.TimeoutInstanceMapper;
import org.ehe.business.timeout.service.TimeoutConfigService;
import org.ehe.business.timeout.service.TimeoutInstanceService;
import org.ehe.common.core.constant.StatusEnum;
import org.ehe.common.core.domain.dto.StartProcessDTO;
import org.ehe.common.core.domain.dto.StartProcessReturnDTO;
import org.ehe.common.core.exception.ServiceException;
import org.ehe.common.core.service.WorkflowService;
import org.ehe.common.core.utils.MapstructUtils;
import org.ehe.common.core.utils.StringUtils;
import org.ehe.common.core.utils.number.MoneyUtils;
import org.ehe.common.core.utils.object.BeanUtils;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.common.satoken.utils.LoginHelper;
import org.ehe.common.sse.dto.SseMessageDto;
import org.ehe.common.sse.utils.SseMessageUtils;
import org.ehe.erp.domain.purchase.ErpPurchaseOrder;
import org.ehe.erp.domain.purchase.ErpPurchaseOrderAttachment;
import org.ehe.erp.domain.purchase.ErpPurchaseOrderItem;
import org.ehe.erp.domain.purchase.bo.ErpPurchaseOrderAttachmentBo;
import org.ehe.erp.domain.purchase.bo.ErpPurchaseOrderBo;
import org.ehe.erp.domain.purchase.bo.ErpPurchaseOrderItemBo;
import org.ehe.erp.domain.purchase.vo.ErpPurchaseOrderAttachmentVo;
import org.ehe.erp.domain.purchase.vo.ErpPurchaseOrderItemVo;
import org.ehe.erp.domain.purchase.vo.ErpPurchaseOrderVo;
import org.ehe.erp.domain.product.vo.ErpProductVo;
import org.ehe.erp.domain.quality.ErpQualityFeedback;
import org.ehe.erp.domain.quality.dto.QualityRecordQueryDto;
import org.ehe.erp.domain.quality.vo.ErpQualityRecordVo;
import org.ehe.erp.domain.quality.vo.ErpQualityTaskVo;
import org.ehe.erp.enums.ErpAuditStatus;
import org.ehe.erp.mapper.purchase.ErpPurchaseOrderItemMapper;
import org.ehe.erp.mapper.purchase.ErpPurchaseOrderMapper;
import org.ehe.erp.mapper.quality.ErpQualityTaskMapper;
import org.ehe.erp.redis.no.ErpNoRedisDAO;
import org.ehe.erp.service.product.IErpProductService;
import org.ehe.erp.service.finance.IErpAccountService;
import org.ehe.erp.service.purchase.IErpPurchaseOrderAttachmentService;
import org.ehe.erp.service.purchase.IErpPurchaseOrderService;
import lombok.RequiredArgsConstructor;
import org.ehe.erp.service.quality.ErpQualityRecordService;
import org.ehe.erp.service.quality.ErpQualityTaskService;
import org.ehe.system.domain.vo.SysUserVo;
import org.ehe.system.service.ISysUserService;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.ehe.common.core.utils.collection.CollectionUtils.*;

/**
 * 采购订单Service业务层处理
 *
 * @author zhangnn
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ErpPurchaseOrderServiceImpl implements IErpPurchaseOrderService {
    private final ErpNoRedisDAO noRedisDAO;
    private final ISysUserService userService;
    private final ErpPurchaseOrderMapper baseMapper;
    private final ErpPurchaseOrderItemMapper baseItemMapper;
    private final IErpProductService erpProductService;
    private final SupplierInfoService erpSupplierService;
    private final IErpAccountService erpAccountService;
    private final BomMasterService bomMasterService;
    private final TimeoutInstanceMapper timeoutInstanceMapper;
    private final ApplicationEventPublisher eventPublisher;
    private final ErpQualityTaskMapper qualityTaskMapper;
    private final ErpQualityRecordService qualityRecordService;
    private final TimeoutConfigMapper timeoutConfigMapper;
    private final WorkflowService workflowService;
    private final IErpPurchaseOrderAttachmentService purchaseOrderAttachmentService;

    /**
     * 查询采购订单
     */
    @Override
    public ErpPurchaseOrderVo queryById(Long id){
        ErpPurchaseOrderVo vo = baseMapper.selectVoById(id);
        if(Objects.isNull(vo)){
            return new ErpPurchaseOrderVo();
        }
        ErpPurchaseOrderBo orderBo = new ErpPurchaseOrderBo();
        orderBo.setId(id);
        List<ErpPurchaseOrderVo> erpPurchaseOrderVos = this.baseMapper.selectVoList(new LambdaQueryWrapper<ErpPurchaseOrder>()
            .eq(ErpPurchaseOrder::getParentId,id));
        // 遍历
        erpPurchaseOrderVos.forEach(p->{
            SupplierInfo supplierInfo = erpSupplierService.getById(p.getSupplierId());
            if(Objects.nonNull(supplierInfo)){
                p.setSupplierName(supplierInfo.getSupplierName());
            }
        });
        vo.setChildOrderVos(erpPurchaseOrderVos);
        // BOM信息
        BomMaster bom = bomMasterService.getById(vo.getBomId());
        if(Objects.nonNull(bom)){
            vo.setBomCode(bom.getBomCode());
            vo.setBomName(bom.getBomName());
        }

        //查看附件信息
        List<ErpPurchaseOrderAttachmentVo> erpPurchaseOrderAttachmentVos = purchaseOrderAttachmentService.listById(id);
        if(Objects.nonNull(erpPurchaseOrderAttachmentVos)){
            vo.setAttachmentVos(erpPurchaseOrderAttachmentVos);
        }
        return vo;
    }

    /**
     * 查询采购订单子项
     */
    @Override
    public List<ErpPurchaseOrderItemVo> queryItemsByOrderNo(String orderNo){
        ErpPurchaseOrderItemBo bo = new ErpPurchaseOrderItemBo();
        bo.setOrderNo(orderNo);
        QueryWrapper<ErpPurchaseOrderItem> lqw = buildItemQueryWrapper(bo);
        List<ErpPurchaseOrderItemVo> erpPurchaseOrderItemVos = baseItemMapper.customPurchaseOrderItemPageList(lqw);
        for (ErpPurchaseOrderItemVo erpPurchaseOrderItemVo : erpPurchaseOrderItemVos) {
            String material = erpPurchaseOrderItemVo.getMaterial();
            if(StringUtils.isNotBlank(material)){
                erpPurchaseOrderItemVo.setFullCode(erpPurchaseOrderItemVo.getCotegoryCode()+"."+material+"."+erpPurchaseOrderItemVo.getCustmoizeCode());
            } else {
                erpPurchaseOrderItemVo.setFullCode(erpPurchaseOrderItemVo.getCotegoryCode()+"."+erpPurchaseOrderItemVo.getCustmoizeCode());
            }
        }

        return  erpPurchaseOrderItemVos;
    }

    /**
     * 查询采购订单列表
     */
    @Override
    public TableDataInfo<ErpPurchaseOrderVo> queryPageList(ErpPurchaseOrderBo bo, PageQuery pageQuery) {
        QueryWrapper<ErpPurchaseOrder> lqw = buildQueryWrapper(bo);
        Page<ErpPurchaseOrderVo> result = baseMapper.selectVoPagebyCustom(pageQuery.build(), lqw);
        List<ErpPurchaseOrderVo> records = result.getRecords();
        //供应商名称
        List<String> supplierNames = new ArrayList<>();
        //根据orderNo查询采购单子项
        records.forEach(o -> {
            ErpPurchaseOrderItemBo itemBo = new ErpPurchaseOrderItemBo();
            itemBo.setOrderNo(o.getNo());
            QueryWrapper<ErpPurchaseOrderItem> itemLqw = buildItemQueryWrapper(itemBo);
            List<ErpPurchaseOrderItemVo> itemVos = baseItemMapper.customPurchaseOrderItemPageList(itemLqw);
            o.setItems(itemVos);
            o.setSupplierName(itemVos.get(0).getSupplierName());
            BomMaster bom = bomMasterService.getById(o.getBomId());
            if(Objects.nonNull(bom)){
                o.setBomId(o.getBomId());
                o.setBomName(bom.getBomName());
                o.setBomCode(bom.getBomCode());
            }
            //查看附件信息
            List<ErpPurchaseOrderAttachmentVo> erpPurchaseOrderAttachmentVos = purchaseOrderAttachmentService.listById(o.getId());
            if(Objects.nonNull(erpPurchaseOrderAttachmentVos)){
                o.setAttachmentVos(erpPurchaseOrderAttachmentVos);
            }
            o.setFilesCount(o.getAttachmentVos().size());
            //质检状态
            ErpQualityTaskVo taskVo = qualityTaskMapper.getByOrderNo(o.getNo());
            if(Objects.isNull(taskVo)){
                o.setCheckResult(0);
                o.setCheckResultName("未质检");
            } else {
                List<ErpQualityRecordVo> recordVos = qualityRecordService.queryNoCheckList(taskVo.getId());
                Map<Integer, Long> resultMap = recordVos.stream()
                    .map(ErpQualityRecordVo::getCheckResult)
                    .filter(checkResult -> checkResult != null)
                    .collect(Collectors.groupingBy(
                        checkResult -> checkResult,
                        Collectors.counting()
                    ));
                //long unChecked = resultMap.getOrDefault(0, 0L);   // 未质检
                long checked = resultMap.getOrDefault(1, 0L);     // 质检完成
                long total = recordVos.size();

                if(total == 0){
                    o.setCheckResult(0);
                    o.setCheckResultName("未质检");
                } else if (checked == total) {
                    o.setCheckResult(1);
                    o.setCheckResultName("质检完成");
                } else {
                    o.setCheckResult(2);
                    o.setCheckResultName("质检中");
                }
            }
        });
        return TableDataInfo.build(result);
    }

    /**
     * 查询采购订单列表
     */
    @Override
    public List<ErpPurchaseOrderVo> queryList(ErpPurchaseOrderBo bo) {
        QueryWrapper<ErpPurchaseOrder> lqw = buildQueryWrapper(bo);
        PageQuery pageQuery = new PageQuery(1,100000);
        return baseMapper.selectVoPagebyCustom(pageQuery.build(), lqw).getRecords();
    }

    private QueryWrapper<ErpPurchaseOrder> buildQueryWrapper(ErpPurchaseOrderBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<ErpPurchaseOrder> lqw = Wrappers.query();
        lqw.eq(StringUtils.isNotBlank(bo.getNo()), "o.no", bo.getNo());
        lqw.eq(null != bo.getId(), "o.parent_id", bo.getId());

        if(null != bo.getParentId() && bo.getParentId() == 0){
            lqw.eq(null != bo.getParentId(),"o.parent_id", bo.getParentId());
        } else {
            lqw.ne(null!= bo.getStatus() && bo.getStatus() == 20, "o.parent_id", 0); // 选择子订单信息进行入库
        }
        lqw.like(StringUtils.isNotBlank(bo.getName()), "o.name", bo.getName());
        lqw.eq(bo.getStatus() != null, "o.status", bo.getStatus());
        lqw.eq(bo.getSupplierId() != null, "o.supplier_id", bo.getSupplierId());
        lqw.eq(bo.getCreateBy() != null,"o.create_by", bo.getCreateBy());
        lqw.eq(bo.getProductId() != null, "i.product_id", bo.getProductId());
        lqw.between(params.get("beginOrderTime") != null && params.get("endOrderTime") != null,
            "o.order_time", params.get("beginOrderTime"), params.get("endOrderTime"));

        // 入库状态。为什么需要 o. 的原因，是因为联表查询时，需要指定表名，不然会报 in_count 错误
        if (Objects.equals(bo.getInStatus(), ErpPurchaseOrderBo.IN_STATUS_NONE)) {
            lqw.eq("o.in_count", 0);
        } else if (Objects.equals(bo.getInStatus(), ErpPurchaseOrderBo.IN_STATUS_PART)) {
            lqw.gt("o.in_count", 0).apply("o.in_count < o.total_count");
        } else if (Objects.equals(bo.getInStatus(), ErpPurchaseOrderBo.IN_STATUS_ALL)) {
            lqw.apply("o.in_count = o.total_count");
        }

        // 退货状态
        if (Objects.equals(bo.getReturnStatus(), ErpPurchaseOrderBo.RETURN_STATUS_NONE)) {
            lqw.eq("o.return_count", 0);
        } else if (Objects.equals(bo.getReturnStatus(), ErpPurchaseOrderBo.RETURN_STATUS_PART)) {
            lqw.gt("o.return_count", 0).apply("o.return_count < o.total_count");
        } else if (Objects.equals(bo.getReturnStatus(), ErpPurchaseOrderBo.RETURN_STATUS_ALL)) {
            lqw.apply("o.return_count = o.total_count");
        }
        // 可采购入库
        if (Boolean.TRUE.equals(bo.getInEnable())) {
            lqw.eq("o.status", ErpAuditStatus.APPROVE.getStatus())
                .apply("o.in_count < o.total_count");
        }
        // 可采购退货
        if (Boolean.TRUE.equals(bo.getReturnEnable())) {
            lqw.eq("o.status", ErpAuditStatus.APPROVE.getStatus())
                .apply("o.return_count < o.in_count");
        }
        //未被删除的采购单
        lqw.eq("o.del_flag", 0);
        //未被删除的采购单子项
        lqw.eq("i.del_flag",0);
        return lqw;
    }

    private QueryWrapper<ErpPurchaseOrderItem> buildItemQueryWrapper(ErpPurchaseOrderItemBo bo) {
        QueryWrapper<ErpPurchaseOrderItem> lqw = Wrappers.query();
        lqw.eq(StringUtils.isNotBlank(bo.getOrderNo()), "i.order_no", bo.getOrderNo());
        lqw.eq("i.del_flag", 0);
        return lqw;
    }
    /**
     * 新增采购订单
     */
    @Override
    @MonitorMethod(bizType = "purchaseOrderOverdue", extractor = PurcharOrderDataExtractor.class)
    @Transactional(rollbackFor = Exception.class)
    public ErpPurchaseOrder insertByBo(ErpPurchaseOrderBo bo) {
        if(null == bo.getParentId()){
            bo.setParentId(0L);
        }
        ErpPurchaseOrder add = MapstructUtils.convert(bo, ErpPurchaseOrder.class);
        // 1.1 校验订单项的有效性
        assert add != null;
        List<ErpPurchaseOrderItem> purchaseOrderItems = validatePurchaseOrderItems(add.getItems());
        // 1.2 校验供应商
        //erpSupplierService.validateSupplier(add.getSupplierId());
        // 1.3 校验结算账户
        if (add.getAccountId() != null) {
            erpAccountService.validateAccount(add.getAccountId());
        }

        // 1.4 生成订单号，并校验唯一性
        String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_IN_NO_PREFIX);
        if (baseMapper.selectByNo(no) != null) {
            throw new ServiceException("生成入库单失败，请重新提交");
        }
        // 2.1 插入订单
        add.setNo(no);
        add.setStatus(Integer.valueOf(StatusEnum.CG.getCode()));
        add.setApproveStatus(String.valueOf(ErpAuditStatus.PENDING_SUBMIT.getStatus()));
        add.setApproveStatus(ErpAuditStatus.PENDING_SUBMIT.getStatus().toString());
        // 响应 截止时间 1小时
        add.setRespondStatus(0);
        int hours = timeoutConfigMapper.getTimeByBizType(BizTypeConstant.PURCHASEORDER);
        add.setRespondEndTime(LocalDateTime.now().plusHours(hours));
        add.setIsOverdue("0");
        add.setIsOverdueEndTime(add.getRespondEndTime());

        calculateTotalPrice(add, purchaseOrderItems);
        boolean erpPurchaseOrderFlag = baseMapper.insert(add) > 0;
        // 2.2 插入订单项
        purchaseOrderItems.forEach(o -> {
            o.setOrderNo(add.getNo());
            if(null != o.getId()){
                o.setId(null);
            }
        });
        boolean erpPurchaseOrderItemFlag = baseItemMapper.insertBatch(purchaseOrderItems);
        bo.setId(add.getId());
        return add;
    }

    /**
     * 修改采购订单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateByBo(ErpPurchaseOrderBo bo) {
        ErpPurchaseOrder update = MapstructUtils.convert(bo, ErpPurchaseOrder.class);
        //1.1校验订单
        assert update != null;
        // 主订单
        if(null == bo.getParentId() || 0 == bo.getParentId()){
            //1小时内响应
            if(null == update.getIsOverdueEndTime()){
                int hours = timeoutConfigMapper.getTimeByBizType(BizTypeConstant.PURCHASEORDER);
                update.setIsOverdueEndTime(LocalDateTime.now().plusHours(hours));
            }
            //采购开始时间默认当前时间
            update.setStartTime(null == bo.getStartTime()?LocalDateTime.now():bo.getStartTime());
            if (update.getTimeoutDuration() != null && update.getTimeoutDuration() > 0) {
                update.setTimeoutAlarmTime(update.getStartTime().plusDays(update.getTimeoutDuration()));
            }
        }
        //子订单
        else {
            ErpPurchaseOrder parentOrder = this.baseMapper.selectById(bo.getParentId());
            //子订单需要更改状态
            update.setStatus(Integer.valueOf(StatusEnum.CGZ.getCode()));
            //跟随主订单信息
            update.setApproveStatus(parentOrder.getApproveStatus());
            update.setIsOverdue(parentOrder.getIsOverdue());
            update.setIsOverdueEndTime(parentOrder.getIsOverdueEndTime());
            update.setTaskDeadline(parentOrder.getTaskDeadline());
            update.setTimeoutDuration(parentOrder.getEstimatedHours());
            update.setTimeoutAlarmTime(parentOrder.getTimeoutAlarmTime());

        }

        validEntityBeforeSave(update);
        // 1.2 校验订单项的有效性
        List<ErpPurchaseOrderItem> purchaseOrderItems = validatePurchaseOrderItems(update.getItems());

        // 2.1 更新订单项
        int i = baseMapper.updateById(update);
        // 2.2 更新订单子项
        updatePurchaseOrderItemList(update.getNo(), purchaseOrderItems);

        // 2.3 更新报警信息
        bo.setUpdateBy(LoginHelper.getUserId());
        //updateTimeInstanceInfo(bo, update);
        return i>0;
    }

    /**
     * 对采购订单作出响应
     * @param id
     * @return
     */
    @Override
    public ErpPurchaseOrder respondOrder(Long id,Integer days) {
        ErpPurchaseOrder order = this.baseMapper.selectById(id);
        order.setUpdateBy(LoginHelper.getUserId());
        order.setApproveStatus(String.valueOf(ErpAuditStatus.SUBMITTED.getStatus()));
        order.setStatus(Integer.valueOf(StatusEnum.SHZ.getCode()));
        order.setRespondTime(LocalDateTime.now());
        order.setEstimatedHours(days);
        order.setTaskDeadline(LocalDateTime.now().plusDays(days));

        order.setIsOverdue(OverdueStatus.PROCESSED);
        if(order.getIsOverdueEndTime().isBefore(LocalDateTime.now())){
            //超期处理
            order.setIsOverdue(OverdueStatus.OVERDUE_AND_PROCESSED);
        }
        //任务截止时间
        this.baseMapper.updateById(order);

        //发起工作流程
        if(order.getStatus().equals(ErpAuditStatus.SUBMITTED.getStatus())){
            StartProcessDTO process = new StartProcessDTO();
            Map<String,Object> map = new HashMap<>();
            map.put("type","purchaseOrder");
            process.setVariables(map);
            process.setFlowCode("purchaseOrder");
            process.setBusinessId(String.valueOf(order.getId()));
            StartProcessReturnDTO processReturnDTO = workflowService.startWorkFlow(process);
            log.info("流程审批发起成功，已启动: projectId={}, engineerId={}", id, LoginHelper.getUsername());
            workflowService.completeTask(processReturnDTO.getTaskId(),"完成该采购任务所需时长"+order.getEstimatedHours()+"天");
        }
        //返回订单信息
        return order;
    }

    /**
     * 提交时间
     * @param id
     * @param days
     * @return
     */
    @Override
    public ErpPurchaseOrder submitDays(Long id, Integer days) {
        ErpPurchaseOrder order = this.baseMapper.selectById(id);
        order.setEstimatedHours(days);
        order.setTaskDeadline(LocalDateTime.now().plusDays(days));

        if(order.getIsOverdueEndTime().isBefore(LocalDateTime.now())){
            order.setIsOverdue(OverdueStatus.OVERDUE_AND_PROCESSED);
        }
        order.setApproveStatus(Integer.valueOf(OverdueStatus.PROCESSED).toString());
        this.baseMapper.updateById(order);
        return order;
    }

    @Override
    public ErpPurchaseOrder approveOrder(Long orderId) {
        ErpPurchaseOrder order = this.baseMapper.selectById(orderId);
        order.setStatus(Integer.valueOf(StatusEnum.CLZ.getCode()));//处理中
        order.setStartTime(LocalDateTime.now());
        order.setApproveStatus(ErpAuditStatus.APPROVE.getStatus().toString());
        this.baseMapper.updateById(order);
        return order;
    }

    @Override
    public ErpPurchaseOrder rejectOrder(Long orderId) {
        ErpPurchaseOrder order = this.baseMapper.selectById(orderId);
        order.setStatus(Integer.valueOf(StatusEnum.CG.getCode())); //待提交
        order.setApproveStatus(ErpAuditStatus.REJECTED.getStatus().toString()); // 3-驳回
        order.setIsOverdue("0");
        int hours = timeoutConfigMapper.getTimeByBizType(BizTypeConstant.PURCHASEORDER);
        order.setIsOverdueEndTime(LocalDateTime.now().plusHours(hours));
        return order;
    }

    /**
     * 更新报警信息
     * @param bo
     * @param update
     */
    private void updateTimeInstanceInfo(ErpPurchaseOrderBo bo, ErpPurchaseOrder update) {
        // 子订单需依照主订单时效进行
        TimeoutInstanceVo timeoutInstanceVo = timeoutInstanceMapper.selectVoOne(new LambdaQueryWrapper<TimeoutInstance>()
            .eq(TimeoutInstance::getBizId, bo.getId())
            .eq(TimeoutInstance::getBizType,BizTypeConstant.PURCHASEORDER)
        );
        if(Objects.nonNull(timeoutInstanceVo)){
            SysUserVo sysUserVo = userService.selectUserById(bo.getUpdateBy());
            if(Objects.nonNull(sysUserVo)){
                timeoutInstanceVo.setUpdateBy(sysUserVo.getNickName());
            }
            timeoutInstanceVo.setDeadlineTime(null==bo.getTimeoutAlarmTime()?timeoutInstanceVo.getDeadlineTime():bo.getTimeoutAlarmTime());
            //提前一小时提醒
            timeoutInstanceVo.setRemindTime(timeoutInstanceVo.getDeadlineTime().minusMinutes(60));
            TimeoutInstance instance = BeanUtils.toBean(timeoutInstanceVo, TimeoutInstance.class);
            timeoutInstanceMapper.updateById(instance);
        } else {
            TimeoutInstance instance = new TimeoutInstance();
            instance.setBizType(BizTypeConstant.PURCHASEORDER);
            instance.setBizId(update.getId());
            instance.setBizName(update.getName());
            instance.setTriggerTime(LocalDateTime.now());
            instance.setDeadlineTime(update.getTimeoutAlarmTime());
            instance.setRemindTime(instance.getDeadlineTime().minusMinutes(30));
            instance.setStatus(BizTypeConstant.WAITING);
            instance.setTenantId(LoginHelper.getTenantId());
            SysUserVo sysUserVo = userService.selectUserById(bo.getCreateBy());
            if(Objects.nonNull(sysUserVo)){
                instance.setCreateBy(sysUserVo.getNickName());
            }
            timeoutInstanceMapper.insert(instance);
        }
    }
    /**
     * 上传采购文件接口
     * @param bo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUploadFiles(ErpPurchaseOrderBo bo) {
        ErpPurchaseOrder purchaseOrder = baseMapper.selectById(bo.getId());
        //上传附件
        List<ErpPurchaseOrderAttachment> attachmentBos = bo.getAttachmentBos();
        for (ErpPurchaseOrderAttachment attachmentBo : attachmentBos) {
            attachmentBo.setPurchaseOrderId(purchaseOrder.getId());
            attachmentBo.setPurchaseOrderNo(purchaseOrder.getNo());
            attachmentBo.setUploadPerson(LoginHelper.getUsername());
            purchaseOrderAttachmentService.save(attachmentBo);
        }
        // 完成订单时
        if (null != bo.getStatus() && bo.getStatus() == 30) {
            this.updatePurchaseOrderStatus(String.valueOf(bo.getId()),bo.getStatus());
        }
        return true;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ErpPurchaseOrder entity) {
        ErpPurchaseOrder purchaseOrder = baseMapper.selectById(entity.getId());
        // 1.1.1 校验订单是否存在和订单状态
        if (purchaseOrder == null) {
            throw new ServiceException("采购订单不存在");
        }
        if (ErpAuditStatus.APPROVE.getStatus().equals(entity.getStatus())) {
            throw new ServiceException("采购订单({" + entity.getNo() + "})已审核，无法修改");
        }
        // 1.1.2 校验供应商
        //erpSupplierService.validateSupplier(entity.getSupplierId());
        // 1.1.3 校验结算账户
        if (entity.getAccountId() != null) {
            erpAccountService.validateAccount(entity.getAccountId());
        }
    }

    /**
     * 批量删除采购订单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        // 参数校验
        if (CollUtil.isEmpty(ids)) {
            throw new ServiceException("待删除的采购订单 ID 列表不能为空");
        }
        boolean flag = false;
        if (Boolean.TRUE.equals(isValid)) {
            // 1. 查询采购订单列表
            List<ErpPurchaseOrder> purchaseOrders = baseMapper.selectBatchIds(ids);
            if (CollUtil.isEmpty(purchaseOrders)) {
                throw new ServiceException("采购订单不存在");
            }

            // 2. 校验状态
            List<ErpPurchaseOrder> approvedOrders = purchaseOrders.stream()
                .filter(purchaseOrder -> ErpAuditStatus.APPROVE.getStatus().equals(purchaseOrder.getStatus()))
                .collect(Collectors.toList());

            if (CollUtil.isNotEmpty(approvedOrders)) {
                String errorNos = approvedOrders.stream()
                    .map(ErpPurchaseOrder::getNo)
                    .collect(Collectors.joining(", "));
                throw new ServiceException("采购订单(" + errorNos + ")已审核，无法删除");
            }

            // 3. 批量删除
            List<String> orderNos = purchaseOrders.stream()
                .map(ErpPurchaseOrder::getNo)
                .collect(Collectors.toList());

            // 3.1 删除采购订单
            int result1 = baseMapper.deleteBatchIds(ids);

            // 3.2 删除订单项
            int result2 = baseItemMapper.updateDelFlagByNos(orderNos, 2);
            if (result1 > 0 && result2 > 0) {
                flag = true;
            }else {
                throw new ServiceException("删除采购订单失败");
            }
        }
        return flag;
    }

    /**
     * 更新订单状态
     * @param id 编号
     * @param status 状态
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updatePurchaseOrderStatus(String id, Integer status) {
        boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status);
        // 1.1 校验存在
        ErpPurchaseOrder purchaseOrder = baseMapper.selectById(id);
        if (ObjectUtil.isEmpty(purchaseOrder)) {
            throw new ServiceException("采购订单不存在");
        }
        // 1.2 校验状态
        if (purchaseOrder.getStatus().equals(status)) {
           String errMessage = approve ? "审核失败，只有未审核的采购订单才能审核" : "反审核失败，只有已审核的采购订单才能反审核";
            throw new ServiceException(errMessage);
        }
        // 1.3 存在采购入单，无法反审核
        if (!approve && purchaseOrder.getInCount().compareTo(BigDecimal.ZERO) > 0) {
            throw new ServiceException("反审核失败，已存在对应的采购入库单");
        }
        // 1.4 存在采购退货单，无法反审核
        if (!approve && purchaseOrder.getReturnCount().compareTo(BigDecimal.ZERO) > 0) {
            throw new ServiceException("反审核失败，已存在对应的采购退货单");
        }


        // 1.5 检查完成时附件状态
        if(status == 30){ //完成的时候
            List<ErpPurchaseOrderAttachmentVo> erpPurchaseOrderAttachmentVos = purchaseOrderAttachmentService.listById(Long.valueOf(id));
            Map<String, Long> attachmentCounts = this.countAttachmentTypes(erpPurchaseOrderAttachmentVos);

            // 定义需要检查的附件类型
            Map<String, String> requiredAttachments = new HashMap<>() {{
                put("采购合同", "采购合同未上传！");
                put("采购照片", "采购照片未上传！");
                put("相关文档", "相关文档未上传！");
            }};

            // 遍历检查所有必填附件
            for (Map.Entry<String, String> entry : requiredAttachments.entrySet()) {
                String type = entry.getKey();
                String errorMsg = entry.getValue();
                // 从Map获取计数，默认0
                long count = attachmentCounts.getOrDefault(type, 0L);
                if (count <= 0) {
                    throw new ServiceException(errorMsg);
                }
            }
            // 2. 更新状态
            int updateCount = baseMapper.updateStatusById(Long.valueOf(id), status);
            if (updateCount == 0) {
                String errMessage = approve ? "审核失败，只有未审核的采购订单才能审核" : "反审核失败，只有已审核的采购订单才能反审核";
                throw new ServiceException(errMessage);
            }

            List<String> ids = new ArrayList<>();
            ids.add(id);
            List<ErpPurchaseOrder> childList = this.baseMapper.selectList(new LambdaQueryWrapper<ErpPurchaseOrder>()
                .eq(ErpPurchaseOrder::getParentId,purchaseOrder.getParentId())
            );
            // 都是已完成的状态
            boolean allStatus30 = childList.stream().allMatch(c -> c.getStatus() == 30);
            // 子订单都是完成的状态时，更新主订单状态
            if(allStatus30){
                //更新父状态
                baseMapper.updateStatusById(childList.get(0).getParentId(), status);
                //存入集合
                ids.add(String.valueOf(childList.get(0).getParentId()));
            }
            //更新预警相关
            ids.forEach( id2 ->{
                TimeoutInstanceVo timeoutInstanceVo = timeoutInstanceMapper.selectVoOne(new LambdaQueryWrapper<TimeoutInstance>()
                    .eq(TimeoutInstance::getBizId, id2)
                    .eq(TimeoutInstance::getBizType, BizTypeConstant.PURCHASEORDER)
                );
                if(Objects.nonNull(timeoutInstanceVo)){
                    timeoutInstanceMapper.updateByComplateTime(id2, BizTypeConstant.PURCHASEORDER);
                    eventPublisher.publishEvent(new RemindEvent(this,timeoutInstanceVo.getId()));
                }
            });

        } else {
            // 2. 更新状态
            int updateCount = baseMapper.updateStatusById(Long.valueOf(id), status);
            if (updateCount == 0) {
                String errMessage = approve ? "审核失败，只有未审核的采购订单才能审核" : "反审核失败，只有已审核的采购订单才能反审核";
                throw new ServiceException(errMessage);
            }
        }
        return true;
    }

    /**
     * 统计附件信息
     * @param attachmentVos
     * @return
     */
    public Map<String, Long> countAttachmentTypes(List<ErpPurchaseOrderAttachmentVo> attachmentVos) {
        if (attachmentVos == null || attachmentVos.isEmpty()) {
            return Map.of(
                "采购照片", 0L,
                "采购合同", 0L,
                "相关文档", 0L,
                "未知类型", 0L
            );
        }

        Map<Integer, Long> typeCountMap = attachmentVos.stream()
            .map(vo -> vo.getAttachmentType() != null ? vo.getAttachmentType() : -1)
            .collect(Collectors.groupingBy(
                Function.identity(),
                Collectors.counting()
            ));

        return Map.of(
            "采购照片", typeCountMap.getOrDefault(1, 0L),
            "采购合同", typeCountMap.getOrDefault(2, 0L),
            "相关文档", typeCountMap.getOrDefault(3, 0L),
            "未知类型", typeCountMap.getOrDefault(-1, 0L)
        );
    }

    /**
     * 验证订单信息
     * @param id 编号
     * @return
     */
    @Override
    public ErpPurchaseOrderVo validatePurchaseOrder(Long id) {
        ErpPurchaseOrderVo purchaseOrder = validatePurchaseOrderExists(id);
        if (ObjectUtil.notEqual(purchaseOrder.getStatus(), ErpAuditStatus.APPROVE.getStatus())) {
            throw new ServiceException("采购订单不存在");
        }
        return purchaseOrder;
    }

    @Override
    public void updatePurchaseOrderInCount(Long id, Map<Long, BigDecimal> inCountMap) {
        List<ErpPurchaseOrderItem> orderItems = baseItemMapper.selectListByOrderId(id);
        // 1. 更新每个采购订单项
        orderItems.forEach(item -> {
            BigDecimal inCount = inCountMap.getOrDefault(item.getId(), BigDecimal.ZERO);
            if (item.getInCount().equals(inCount)) {
                return;
            }
            if (inCount.compareTo(item.getCount()) > 0) {
                throw new ServiceException("采购订单项({})超过最大允许入库数量({})");
            }
            ErpPurchaseOrderItem erpPurchaseOrderItem = new ErpPurchaseOrderItem();
            erpPurchaseOrderItem.setId(item.getId());
            erpPurchaseOrderItem.setInCount(inCount);
            baseItemMapper.updateById(erpPurchaseOrderItem);
        });
        // 2. 更新采购订单
        BigDecimal totalInCount = getSumValue(inCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO);
        ErpPurchaseOrder order = new ErpPurchaseOrder();
        order.setId(id);
        order.setInCount(totalInCount);
        baseMapper.updateById(order);
    }

    private ErpPurchaseOrderVo validatePurchaseOrderExists(Long id) {
        ErpPurchaseOrderVo purchaseOrder = baseMapper.selectVoById(id);
        if (purchaseOrder == null) {
            throw new ServiceException("采购订单不存在");
        }
        return purchaseOrder;
    }

    private List<ErpPurchaseOrderItem> validatePurchaseOrderItems(List<ErpPurchaseOrderItem> list) {
        // 1. 校验产品存在
        List<ErpProductVo> productList = erpProductService.validProductList(
            convertSet(list, ErpPurchaseOrderItem::getProductId));
        Map<Long, ErpProductVo> productMap = convertMap(productList, ErpProductVo::getId);
        // 2. 转化为 ErpPurchaseOrderItem 列表
        return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseOrderItem.class, item -> {
            item.setProductUnitId(productMap.get(item.getProductId()).getUnitId());
            item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount()));
            if (item.getTotalPrice() == null) {
                return;
            }
            if (item.getTaxPercent() != null) {
                item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent()));
            }
        }));
    }

    private void calculateTotalPrice(ErpPurchaseOrder purchaseOrder, List<ErpPurchaseOrderItem> purchaseOrderItems) {
        purchaseOrder.setTotalCount(getSumValue(purchaseOrderItems, ErpPurchaseOrderItem::getCount, BigDecimal::add));
        purchaseOrder.setTotalProductPrice(getSumValue(purchaseOrderItems, ErpPurchaseOrderItem::getTotalPrice, BigDecimal::add, BigDecimal.ZERO));
        purchaseOrder.setTotalTaxPrice(getSumValue(purchaseOrderItems, ErpPurchaseOrderItem::getTaxPrice, BigDecimal::add, BigDecimal.ZERO));
        purchaseOrder.setTotalPrice(purchaseOrder.getTotalProductPrice().add(purchaseOrder.getTotalTaxPrice()));
        // 计算优惠价格
        if (purchaseOrder.getDiscountPercent() == null) {
            purchaseOrder.setDiscountPercent(BigDecimal.ZERO);
        }
        purchaseOrder.setDiscountPrice(MoneyUtils.priceMultiplyPercent(purchaseOrder.getTotalPrice(), purchaseOrder.getDiscountPercent()));
        purchaseOrder.setTotalPrice(purchaseOrder.getTotalPrice().subtract(purchaseOrder.getDiscountPrice()));
    }
    private void updatePurchaseOrderItemList(String no, List<ErpPurchaseOrderItem> newList) {
        // 第一步，对比新老数据，获得添加、修改、删除的列表
        LambdaQueryWrapper<ErpPurchaseOrderItem> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(no), ErpPurchaseOrderItem::getOrderNo, no);
        List<ErpPurchaseOrderItem> oldList = baseItemMapper.selectList(lqw);
        // id 不同，就认为是不同的记录
        List<List<ErpPurchaseOrderItem>> diffList = diffList(oldList, newList,
            (oldVal, newVal) -> oldVal.getOrderNo().equals(newVal.getOrderNo()));

        // 第二步，批量添加、修改、删除
        if (CollUtil.isNotEmpty(diffList.get(0))) {
            diffList.get(0).forEach(o -> o.setOrderNo(no));
            baseItemMapper.insertBatch(diffList.get(0));
        }
        if (CollUtil.isNotEmpty(diffList.get(1))) {
            baseItemMapper.updateBatchById(diffList.get(1));
        }
        if (CollUtil.isNotEmpty(diffList.get(2))) {
            baseItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpPurchaseOrderItem::getId));
        }
    }

    /**
     * 根据采购订单编号获取详情
     * @param no
     * @return
     */
    @Override
    public ErpPurchaseOrder queryByOrderNo(String no) {
        return this.baseMapper.selectByNo(no);
    }


    /**
     * 生成子订单
     * @param id 父订单ID
     * @return 创建的订单数量
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ErpPurchaseOrderVo createChildOrderBySupplierId(Long id) {
        // 1. 参数校验
        if (id == null) {
            throw new ServiceException("父订单ID不能为空");
        }

        // 2. 查询父订单信息
        ErpPurchaseOrderVo parentOrder = this.baseMapper.selectVoById(id);
        if (parentOrder == null) {
            throw new ServiceException("父订单不存在");
        }

        // 3. 检查是否已经生成过子订单
        List<ErpPurchaseOrder> existingChildOrders = baseMapper.selectList(
            new LambdaQueryWrapper<ErpPurchaseOrder>()
                .eq(ErpPurchaseOrder::getParentId, id)
                .eq(ErpPurchaseOrder::getDelFlag, 0)
        );

        if (CollUtil.isNotEmpty(existingChildOrders)) {
            throw new ServiceException("该订单已经生成过子订单，不能重复生成。现有子订单数量: " + existingChildOrders.size());
        }

        // 4. 获取父订单的所有订单项
        List<ErpPurchaseOrderItem> allOrderItems = baseItemMapper.selectList(
            new LambdaQueryWrapper<ErpPurchaseOrderItem>()
                .eq(ErpPurchaseOrderItem::getOrderNo, parentOrder.getNo())
                .eq(ErpPurchaseOrderItem::getDelFlag, 0)
        );

        if (CollUtil.isEmpty(allOrderItems)) {
            throw new ServiceException("父订单中没有订单项，无法生成子订单");
        }

        allOrderItems.forEach(s->{
            if(null == s.getSupplierId()){
                throw new ServiceException("存在没有指定供应商物料信息，请编辑确认！");
            }
        });

        // 5. 过滤出有供应商的订单项
        List<ErpPurchaseOrderItem> invalidItems = allOrderItems.stream()
            .filter(item -> item.getSupplierId() != null)
            .collect(Collectors.toList());

        // 6. 按供应商分组并合并相同产品
        Map<Long, List<ErpPurchaseOrderItem>> supplierGroupMap = groupAndMergeBySupplier(invalidItems);

        AtomicInteger index = new AtomicInteger(1);
        AtomicInteger successCount = new AtomicInteger(0);

        // 7. 为每个供应商创建一个采购订单
        supplierGroupMap.forEach((supplierId, materials) -> {
            try {
                String currentIndex = String.format("%02d", index.getAndIncrement());
                //创建供应商订单
                createPurchaseOrderForSupplier(parentOrder, currentIndex, supplierId, materials);
                successCount.incrementAndGet();
                log.info("成功为供应商{}创建采购订单", supplierId);
            } catch (Exception e) {
                log.error("为供应商{}生成采购订单失败: {}", supplierId, e.getMessage(), e);
                throw new ServiceException("为供应商" + supplierId + "生成采购订单失败: " + e.getMessage());
            }
        });

        //修改主订单状态为  采购中
        ErpPurchaseOrder order = this.baseMapper.selectById(parentOrder.getId());
        order.setStatus(Integer.valueOf(StatusEnum.CGZ.getCode()));
        this.baseMapper.updateById(order);

        return parentOrder;
    }

    /**
     * 按供应商分组并合并相同产品
     */
    private Map<Long, List<ErpPurchaseOrderItem>> groupAndMergeBySupplier(List<ErpPurchaseOrderItem> items) {
        Map<Long, List<ErpPurchaseOrderItem>> supplierGroupMap = new HashMap<>();

        // 按供应商分组
        Map<Long, List<ErpPurchaseOrderItem>> tempGroupMap = items.stream()
            .collect(Collectors.groupingBy(ErpPurchaseOrderItem::getSupplierId));

        // 对每个供应商的订单项进行产品合并
        tempGroupMap.forEach((supplierId, supplierItems) -> {
            // 按产品ID分组
            Map<Long, List<ErpPurchaseOrderItem>> productGroupMap = supplierItems.stream()
                .collect(Collectors.groupingBy(ErpPurchaseOrderItem::getProductId));

            List<ErpPurchaseOrderItem> mergedItems = new ArrayList<>();

            productGroupMap.forEach((productId, productItems) -> {
                if (productItems.size() == 1) {
                    // 只有一个，直接添加
                    mergedItems.add(productItems.get(0));
                } else {
                    // 多个相同产品，需要合并
                    ErpPurchaseOrderItem mergedItem = mergeProductItems(productItems);
                    mergedItems.add(mergedItem);
                    log.info("供应商[{}]的产品[{}]存在{}个重复项，已合并", supplierId, productId, productItems.size());
                }
            });

            supplierGroupMap.put(supplierId, mergedItems);
        });

        return supplierGroupMap;
    }

    /**
     * 合并相同产品的订单项
     */
    private ErpPurchaseOrderItem mergeProductItems(List<ErpPurchaseOrderItem> items) {
        if (CollUtil.isEmpty(items)) {
            throw new ServiceException("合并的订单项列表不能为空");
        }

        ErpPurchaseOrderItem firstItem = items.get(0);
        ErpPurchaseOrderItem mergedItem = new ErpPurchaseOrderItem();

        // 复制基本信息（使用第一个item的信息）
        mergedItem.setProductId(firstItem.getProductId());
        mergedItem.setProductUnitId(firstItem.getProductUnitId());
        mergedItem.setSupplierId(firstItem.getSupplierId());

        // 合并数量和价格相关字段
        BigDecimal totalCount = items.stream()
            .map(ErpPurchaseOrderItem::getCount)
            .filter(Objects::nonNull)
            .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 计算加权平均价格
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal totalQuantity = BigDecimal.ZERO;

        for (ErpPurchaseOrderItem item : items) {
            if (item.getCount() != null && item.getProductPrice() != null) {
                BigDecimal itemAmount = item.getProductPrice().multiply(item.getCount());
                totalAmount = totalAmount.add(itemAmount);
                totalQuantity = totalQuantity.add(item.getCount());
            }
        }

        BigDecimal avgPrice = totalQuantity.compareTo(BigDecimal.ZERO) > 0
            ? totalAmount.divide(totalQuantity, 6, RoundingMode.HALF_UP)
            : firstItem.getProductPrice();

        mergedItem.setCount(totalCount);
        mergedItem.setProductPrice(avgPrice);
        mergedItem.setTotalPrice(avgPrice.multiply(totalCount));

        // 使用第一个item的税率，如果为空则使用13%
        BigDecimal taxPercent = firstItem.getTaxPercent() != null
            ? firstItem.getTaxPercent()
            : BigDecimal.valueOf(13);
        mergedItem.setTaxPercent(taxPercent);
        mergedItem.setTaxPrice(MoneyUtils.priceMultiplyPercent(mergedItem.getTotalPrice(), taxPercent));

        // 合并备注信息
        String mergedRemark = items.stream()
            .map(ErpPurchaseOrderItem::getRemark)
            .filter(StringUtils::isNotBlank)
            .distinct()
            .collect(Collectors.joining("; "));
        mergedItem.setRemark("合并项: " + mergedRemark);

        // 初始化其他字段
        mergedItem.setInCount(BigDecimal.ZERO);
        mergedItem.setReturnCount(BigDecimal.ZERO);

        return mergedItem;
    }

    /**
     * 为指定供应商创建采购订单 - 增加重复校验
     */
    private void createPurchaseOrderForSupplier(ErpPurchaseOrderVo parentOrder,String currentIndex,
                                                Long supplierId, List<ErpPurchaseOrderItem> materials) {

        log.info("为供应商{}创建采购订单，物料数量: {}", supplierId, materials.size());

        // 1. 再次检查是否已经为该供应商创建过子订单
        List<ErpPurchaseOrder> existingOrders = baseMapper.selectList(
            new LambdaQueryWrapper<ErpPurchaseOrder>()
                .eq(ErpPurchaseOrder::getParentId, parentOrder.getParentId())
                .eq(ErpPurchaseOrder::getSupplierId, supplierId)
                .eq(ErpPurchaseOrder::getDelFlag, 0)
        );

        if (CollUtil.isNotEmpty(existingOrders)) {
            throw new ServiceException("供应商[" + supplierId + "]已经存在子订单，不能重复创建");
        }

        // 2. 校验供应商是否存在
        try {
            erpSupplierService.validateSupplier(supplierId);
        } catch (Exception e) {
            throw new ServiceException("供应商[" + supplierId + "]不存在或无效");
        }

        // 3. 创建采购订单BO
        ErpPurchaseOrderBo orderBo = new ErpPurchaseOrderBo();

        // 设置基本信息
        orderBo.setSupplierId(parentOrder.getSupplierId());
        orderBo.setParentId(parentOrder.getId());
        orderBo.setBomId(parentOrder.getBomId());
        orderBo.setName(parentOrder.getName() + "—" + currentIndex);
        orderBo.setSupplierId(supplierId);
        orderBo.setOrderTime(new Date());
        orderBo.setStartTime(parentOrder.getStartTime());
        orderBo.setTimeoutDuration(parentOrder.getTimeoutDuration());
        orderBo.setTimeoutAlarmTime(parentOrder.getTimeoutAlarmTime());
        orderBo.setCompleteTime(parentOrder.getCompleteTime());
        orderBo.setStatus(Integer.valueOf(StatusEnum.CGZ.getCode()));
        orderBo.setEstimatedHours(parentOrder.getEstimatedHours());
        orderBo.setTimeoutDuration(parentOrder.getTimeoutDuration());
        orderBo.setIsOverdue(parentOrder.getIsOverdue());
        orderBo.setApproveStatus(String.valueOf(ErpAuditStatus.PROCESS.getStatus()));
        orderBo.setRemark("由总订单[ID:" + parentOrder.getParentId() + "]自动生成，供应商ID:" + supplierId);

        // 设置默认值
        orderBo.setDiscountPercent(BigDecimal.ZERO);
        orderBo.setDiscountPrice(BigDecimal.ZERO);
        orderBo.setDepositPrice(BigDecimal.ZERO);
        orderBo.setInCount(BigDecimal.ZERO);
        orderBo.setReturnCount(BigDecimal.ZERO);

        // 4. 设置订单项
        orderBo.setItems(materials);

        // 5. 调用采购订单服务保存
        ErpPurchaseOrder order = this.insertByBo(orderBo);
        log.info("成功为供应商{}创建采购订单，订单号: {}", supplierId, order.getNo());
    }

    /**
     * 检查父订单是否可以生成子订单
     */
    private void validateParentOrderForChildGeneration(ErpPurchaseOrderVo parentOrder) {
        // 检查父订单状态
        if (!ErpAuditStatus.PROCESS.getStatus().equals(parentOrder.getStatus())
            && !ErpAuditStatus.APPROVE.getStatus().equals(parentOrder.getStatus())) {
            throw new ServiceException("只有待审核或已审核的订单才能生成子订单");
        }

        // 检查是否已经有入库记录
        if (parentOrder.getInCount() != null && parentOrder.getInCount().compareTo(BigDecimal.ZERO) > 0) {
            throw new ServiceException("该订单已有入库记录，不能生成子订单");
        }
    }

}
